<template>

    <div  style="border: 1px solid #ccc">
      <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
      <Editor style="height: 500px;  overflow-y: hidden;" class="mb-editor" v-model="valueHtml" :defaultConfig="editorConfig" :mode="mode"
        @onCreated="handleCreated" 
        @customPaste="customPaste"  
      />
    </div>
    
</template>

<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css'; // 引入 css
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import { SlateElement, IEditorConfig, IDomEditor } from "@wangeditor/editor";

import { fetchUpload } from '@/server';

type InsertFnType =  any;

type ImageElement = SlateElement & {
  src: string;
  alt: string;
  url: string;
  href: string;
};

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef();
// `<img src="http://localhost:8007/uploads/6355843f4b08ece85f06f0fa/topicImg-1666908518024.webp" alt="topicImg-1666908518024.webp">`;
// `<el-image  class="px-1"  style="width: 100px; height: 100px" src="http://localhost:8007/uploads/6355843f4b08ece85f06f0fa/topicImg-1666908518024.webp" :preview-src-list="['http://localhost:8007/uploads/6355843f4b08ece85f06f0fa/topicImg-1666908518024.webp']" fit="cover" />`;

// `<div class="el-image px-1" data-v-c3a1e627="" style="width: 9rem; height: 9rem;"><img alt="topicImg-1666548950052.png" src="http://localhost:8007/uploads/topicImg-1666548950052.png" class="el-image__inner el-image__preview" style="object-fit: cover;"><!--v-if--><!--v-if--></div>`;



// 内容 HTML
const valueHtml = ref('<p></p>');
//模式
const mode = ref('default')
// 模拟 ajax 异步获取内容
// onMounted(() => {
//   setTimeout(() => {
//     valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>'
//   }, 1500)
// })

const toolbarConfig = {}
const editorConfig: Partial<IEditorConfig> = {  // TS 语法
  placeholder: '请输入内容...',
  MENU_CONF: {}
  // 其他属性...
}

// 组件销毁时，也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value
  if (editor == null) return
  editor.destroy()
})

const handleCreated = (editor:any) => {
  editorRef.value = editor // 记录 editor 实例，重要！

}



// 自定义校验图片
function customCheckImageFn(src: string, alt: string, url: string): boolean | undefined | string { // TS 语法
  // function customCheckImageFn(src, alt, url) {                                                    // JS 语法
  if (!src) {
    return
  }
  if (src.indexOf('http') !== 0) {
    return '图片网址必须以 http/https 开头'
  }
  return true

  // 返回值有三种选择：
  // 1. 返回 true ，说明检查通过，编辑器将正常插入图片
  // 2. 返回一个字符串，说明检查未通过，编辑器会阻止插入。会 alert 出错误信息（即返回的字符串）
  // 3. 返回 undefined（即没有任何返回），说明检查未通过，编辑器会阻止插入。但不会提示任何信息
}

// 转换图片链接
function customParseImageSrc(src: string): string {  // TS 语法
  // function customParseImageSrc(src) {               // JS 语法
  if (src.indexOf('http') !== 0) {
    return `http://${src}`
  }
  return src
}

// 插入图片
editorConfig.MENU_CONF!['insertImage'] = {
  onInsertedImage(imageNode: ImageElement | null) {  // TS 语法
    // onInsertedImage(imageNode) {                    // JS 语法
    if (imageNode == null) return

    const { src, alt, url, href } = imageNode
    console.log('inserted image', src, alt, url, href)
  },
  checkImage: customCheckImageFn, // 也支持 async 函数
  parseImageSrc: customParseImageSrc, // 也支持 async 函数
}
// 编辑图片
editorConfig.MENU_CONF!['editImage'] = {
  onUpdatedImage(imageNode: ImageElement | null) {  // TS 语法
    // onUpdatedImage(imageNode) {                    // JS 语法
    if (imageNode == null) return

    const { src, alt, url } = imageNode
    console.log('updated image', src, alt, url)
  },
  checkImage: customCheckImageFn, // 也支持 async 函数
  parseImageSrc: customParseImageSrc, // 也支持 async 函数
}

//上传图片
editorConfig.MENU_CONF!['uploadImage'] = {
  // server: '/api/upload',
  // form-data fieldName ，默认值 'wangeditor-uploaded-image'
  fieldName: 'topicImg',
  // 自定义上传

  async customUpload(file: File, insertFn: InsertFnType) {  // TS 语法
    // async customUpload(file, insertFn) {                   // JS 语法
        // file 即选中的文件
        // 自己实现上传，并得到图片 url alt href
        // 最后插入图片
        const formData = new FormData()
        formData.append('topicImg',file)
        const data = await fetchUpload(formData)
        insertFn(data.url, data.alt,data.href)
  },

  // 单个文件的最大体积限制，默认为 2M
  maxFileSize: 10 * 1024 * 1024, // 1M

  // 最多可上传几个文件，默认为 100
  maxNumberOfFiles: 10,

  // 选择文件时的类型限制，默认为 ['image/*'] 。如不想限制，则设置为 []
  allowedFileTypes: ['image/*'],

  // 自定义上传参数，例如传递验证的 token 等。参数会被添加到 formData 中，一起上传到服务端。
  // meta: {
  //   token: 'xxx',
  //   otherKey: 'yyy'
  // },

  // 将 meta 拼接到 url 参数中，默认 false
  // metaWithUrl: false,

  // 自定义增加 http  header
  headers: {
    Accept: ['jpg', 'jpeg', 'png', 'gif', 'bmp'],
    'Access-Control-Allow-Origin': 'origin',
  },

  // 跨域是否传递 cookie ，默认为 false
  withCredentials: true,

  // 超时时间，默认为 10 秒
  timeout: 10 * 1000, // 5 秒

}

//自定义粘贴事件
const customPaste = (editor: IDomEditor, event: ClipboardEvent | any): boolean => {     // TS 语法
  // editorConfig.customPaste = (editor, event) => {                                       // JS 语法

  // event 是 ClipboardEvent 类型，可以拿到粘贴的数据
  // 可参考 https://developer.mozilla.org/zh-CN/docs/Web/API/ClipboardEvent

  // const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
  // const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
  // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据（如从 word wsp 复制粘贴）

  // 同步
  // editor.insertText('xxx')

  // 异步
  // setTimeout(() => {
  //   editor.insertText('yy')
  // }, 1000)

  //阻止冒泡
  // event.stopPropagation();
  // 阻止默认的粘贴行为
  // event.preventDefault()
  // return false

  const items = (event.clipboardData || window.Clipboard).items
  //保护条款,禁止图片错误粘贴
  for (let i = 0; i < items.length; i++) {
    if (items[i].type.indexOf('image') !== -1) {
      editor.insertBreak()   
      break
      
    }
  }
  // editor.deleteBackward('character')
  // console.log(editor.isFocused())  
  
  // 继续执行默认的粘贴行为
  return true
}

const emit = defineEmits(['on-valueHtml'])

onMounted(async function(){
  await nextTick()
  emit('on-valueHtml',valueHtml,editorRef.value)
  
})


</script>

<style lang="scss" scoped>
.mb-editor{
  @media screen and (max-width:640px){
    height: 300px !important;
  }
  @media screen and (min-width:640px) and (max-width:768px){
    height: 330px !important;
  }
  @media screen and (min-width:768px) and (max-width:1024px){
    height: 400px !important;
  }
  @media screen and (min-width:1024px) and (max-width:1280px){
    height: 450px !important;
  }
}
</style>